import logging
import wsgiref.handlers
import os
import re
import random

from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db

class Grid(db.Model):
  owner = db.UserProperty()
  title = db.StringProperty()
  top = db.StringProperty()
  bottom = db.StringProperty()
  left = db.StringProperty()
  right = db.StringProperty()

class Point(db.Model):
  grid = db.ReferenceProperty(Grid)
  label = db.StringProperty()

class Entry(db.Model):
  point = db.ReferenceProperty(Point)
  x = db.FloatProperty()
  y = db.FloatProperty()
  user = db.UserProperty()

class MainPage(webapp.RequestHandler):
  def get(self):
    curUser = users.get_current_user()

    if not curUser:
      self.redirect(users.create_login_url(self.request.uri))
      return
    
    id = self.request.uri
    id = re.compile(".*Versus/([^/]+)$").match(id) 
    if id:
      id = id.group(1)
      grid = db.Model.get(id)
      grid = '"%s"' % (grid.title,)
    else:
      grids = Grid.all()
      index = random.randint(0, grids.count(1000) - 1)
      grid = grids.fetch(1, index)[0]
      id = str(grid.key())
      grid = '"%s"' % (grid.title,)


    data = {
       'user': curUser.email(),
       'logout': users.create_logout_url('/'),
       'grid': grid,
       'id': id,
       'mygrids': [],
       # TODO do real searching
       'allgrids': []
    }

    grids = Grid.all()
    #grids.filter("owner =", curUser)
    for grid in grids:
      info = {"title": grid.title, "id": str(grid.key())}
      if grid.owner == curUser:
        info["mine"] = True
      data["allgrids"].append(info)


    path = os.path.join(os.path.dirname(__file__), 'index.html')
    self.response.out.write(template.render(path, data))

class GridPage(webapp.RequestHandler):
  def get(self):
    curUser = users.get_current_user()
    if not curUser:
      self.response.out.write('must be logged in')
      return

    id = re.compile(".*Grid/([^/]+)$").match(self.request.uri)
    if not id:
      self.response.out.write('need a grid id')
      return

    grid = db.Model.get(id.group(1))

    data = { "points": {} }

    points = Point.all()
    points.filter("grid =", grid)
    logging.debug("fetching points")
    for point in points:
      entries = Entry.all()
      entries.filter("point =", point)
      # We use a two-entry list instead of a tuple so we can pass  it straight
      # through to javascript
      result = [[]]
      for entry in entries:
        if entry.user.email == curUser.email:
          result[0] = [entry.x, entry.y]
        else:
          result.append([entry.x, entry.y])
      # TODO fix this so it's still unicode/i18n friendly
      data["points"][str(point.label)] = result

    data['top'] = grid.top
    data['bottom'] = grid.bottom
    data['left'] = grid.left
    data['right'] = grid.right

    path = os.path.join(os.path.dirname(__file__), 'grid.svg')
    self.response.headers["Content-Type"] = "image/svg+xml"
    self.response.out.write(template.render(path, data))
    logging.debug('grid served')

class CreatePage(webapp.RequestHandler):
  def post(self):
    curUser = users.get_current_user()
    if not curUser:
      self.redirect(users.create_login_url(self.request.uri))

    # TODO more sanitization of input
    grid = Grid(
      owner = curUser,
      title = self.request.get("title"),
      top = self.request.get("top"),
      bottom = self.request.get("bottom"),
      left = self.request.get("left"),
      right = self.request.get("right")).put()

    self.redirect("/Versus/%s" % (grid,))

class PointPage(webapp.RequestHandler):
  def get(self):
    curUser = users.get_current_user()
    # TODO: refactor error checking as exceptions
    if not curUser:
      self.response.out.write("handleError('not logged in')")
      return
      
    id = re.compile(".*Point/([^?/]+).*$").match(self.request.uri) 
    if not id:
      self.response.out.write("handleError('no grid id in url')")
      return
      
    labelVal = self.request.get("label")
    if not labelVal:
      self.response.out.write("handleError('no label name in url')")
      return

    id = id.group(1)
    dbgrid = db.Model.get(id)
    if not dbgrid:
      self.response.out.write("no grid with id '%s'" % id)
      return

    # Get the point with this name
    q = Point.all()
    q.filter("grid =", dbgrid)
    q.filter("label =", labelVal)
    points = q.fetch(1)

    if len(points) > 0:
      point = points[0]
    else:
      # create it
      point = Point(grid = dbgrid, label = labelVal)
      point.put()

    # Get this user's entry, if any
    q = Entry.all()
    q.filter("point =", point)
    q.filter("user =", curUser)
    entries = q.fetch(1)

    x = float(self.request.get("x", 0))
    y = float(self.request.get("y", 0))

    # update or create entry
    if len(entries) > 0:
      entry = entries[0]
      entry.x = x
      entry.y = y
    else:
      entry = Entry(
          point = point,
          user = curUser,
          x = x,
          y = y)
    entry.put()

    logging.debug('label %s saved at (%f, %f)' % (labelVal, x, y))
    self.response.out.write("handleSubmit()")

def main():
  application = webapp.WSGIApplication(
                                       [
                                        ('/', MainPage),
                                        ('/Versus.*', MainPage),
                                        ('/Grid/.*', GridPage),
                                        ('/Create', CreatePage),
                                        ('/Point/.*', PointPage)
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()
